package io.github.gszj2018.jp_analysis;

import io.github.gszj2018.jp_analysis.target.Constraint;
import io.github.gszj2018.jp_analysis.target.Target;

import java.util.*;
import java.util.stream.Collectors;

public class AndersonSolver {
    public final Map<String, Map<String, Set<Integer>>> v = new HashMap<>();
    public final Map<Integer, Map<String, Set<Integer>>> hf = new HashMap<>();
    private final List<Constraint> constraints = new ArrayList<>();
    private final Map<Integer, Target> queries = new HashMap<>();

    public void addConstraint(Target dst, Target src) {
        if (dst != Target.UNSUPPORTED && src != Target.UNSUPPORTED) {
            constraints.add(new Constraint(dst, src));
        }
    }

    public void addQuery(int id, Target v) {
        queries.put(id, v);
    }

    public List<String> getPrintableResult() {
        return queries.entrySet().stream()
                .sorted(Comparator.comparingInt(Map.Entry::getKey))
                .map(q -> {
                    StringBuilder str = new StringBuilder();
                    str.append(q.getKey().toString()).append(":");
                    Set<Integer> result =
                            q.getValue().resolve(this);
                    result.stream().sorted().forEach(x ->
                            str.append(" ").append(x.toString()));
                    return str.toString();
                })
                .collect(Collectors.toList());
    }

    public void solve() {
        boolean modified;
        do {
            modified = false;
            for (Constraint c : constraints) {
                boolean cur = expandSet(c.dst, c.src);
                modified = modified || cur;
            }
        } while (modified);
    }

    private boolean expandSet(Target dst, Target src) {
        return dst.expandTargetSet(this, src.resolve(this));
    }


}
